//package com.geek.factory.controller;
//
//import cn.hutool.core.util.ObjectUtil;
//import cn.hutool.core.util.StrUtil;
//import cn.hutool.json.JSONUtil;
//import com.geek.factory.constant.MessageConstant;
//import com.geek.factory.constant.RedisTokenConstant;
//import com.geek.factory.dto.LoginDTO;
//import com.geek.factory.entity.User;
//import com.geek.factory.exception.FactoryException;
//import com.geek.factory.exception.RefreshTokenInvalidException;
//import com.geek.factory.result.Result;
//import com.geek.factory.constant.SuccessConstant;
//import com.geek.factory.security.LoginUser;
//import com.geek.factory.service.SmsService;
//import com.geek.factory.service.UserService;
//import com.geek.factory.utils.JwtHelper;
//import com.geek.factory.vo.UserQueryVO;
//import io.swagger.annotations.Api;
//import io.swagger.annotations.ApiOperation;
//import io.swagger.annotations.ApiParam;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.security.authentication.AuthenticationManager;
//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
//import org.springframework.security.core.Authentication;
//import org.springframework.security.core.context.SecurityContextHolder;
//import org.springframework.util.ObjectUtils;
//import org.springframework.util.StringUtils;
//import org.springframework.web.bind.annotation.*;
//import java.util.HashMap;
//import java.util.Map;
//
///**
// * @author chenmin
// * @desc TODO
// * @date 2025/6/10
// */
////@RestController
////@RequestMapping("/admin")
////@Slf4j
//@RestController
////@RequestMapping("/admin/auth")
//@Api(tags = "后台系统-登录认证接口")
//public class AuthController {
//@Autowired
//private UserService userService;
//    @Autowired
//    private SmsService smsService;
//    @Autowired
//    private AuthenticationManager authenticationManager;
//
//    @Autowired
//    private RedisTemplate<String,Object> redisTemplate;
//    @ApiOperation("手机号验证码登录")
//    @PostMapping("loginByPhone")
//    public Result loginByPhone(@ApiParam("手机号验证码登录数据") @RequestBody LoginDTO dto) {
//        // 1. 校验参数
//        if (!StringUtils.hasLength(dto.getPhone()) || !StringUtils.hasLength(dto.getCode())) {
//            return new Result(SuccessConstant.FAIL, MessageConstant.TELEPHONE_VALIDATECODE_NOTNULL);
//        }
//        // 2. 校验验证码
//        boolean valid = smsService.checkCode(dto.getPhone(), dto.getCode());
//        if (!valid) {
//            return new Result(SuccessConstant.FAIL, MessageConstant.VALIDATECODE_ERROR);
//        }
//        // 3. 查询用户
//        User user = userService.getOneByPhone(dto.getPhone());
//        if (user == null) {
//            return new Result(SuccessConstant.FAIL, MessageConstant.GET_USER_FAIL);
//        }
//        // 4. 生成token
//        String accessToken = JwtHelper.createToken(user.getId().longValue(), user.getUsername());
//        String refreshToken = JwtHelper.refreshToken(accessToken);
//        Map<String, Object> map = new HashMap<>();
//        map.put("accessToken", accessToken);
//        map.put("refreshToken", refreshToken);
//        // 5. 返回
//        return new Result(SuccessConstant.SUCCESS, MessageConstant.LOGIN_SUCCESS, map);
//    }
//
//    @ApiOperation("登录")
//    @PostMapping("login")
//    public Result login(@ApiParam("后端登录数据") @RequestBody UserQueryVO vo){
//        //添加SpringSecurity之后  认证
//
//        if(StrUtil.isEmpty(vo.getUsername()) || StrUtil.isEmpty(vo.getPassword())){
//            throw new FactoryException(MessageConstant.LOGIN_FAIL);
//        }
//        //1.获取认证管理器中的认证信息
//        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(vo.getUsername() , vo.getPassword());
//        //调用自定义的UserDetailsService中loadUserByUsername
//        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
//        //认证不通过
//        if(ObjectUtils.isEmpty(authenticate)){
//            throw new FactoryException(MessageConstant.LOGIN_FAIL);
//        }
//
//        //认证通过
//        LoginUser loginUser = (LoginUser)authenticate.getPrincipal();
//        if(loginUser!=null){
//            User user = loginUser.getUser();
//            Map<String, Object> map = new HashMap<>();
//            //创建token数据并响应
//            // 创建访问Token令牌
//            String accessToken = JwtHelper.createToken(user.getId().longValue(), user.getUsername());
//            // 创建刷新Token令牌
//            String refreshToken = JwtHelper.refreshToken(accessToken);
//            map.put("accessToken", accessToken);
//            map.put("refreshToken", refreshToken);
//
//            //在Redis中存储一份认证通过的用户信息
//            redisTemplate.opsForValue().set(RedisTokenConstant.USER_TOKEN+"::"+user.getId() , JSONUtil.toJsonStr(user));
//            //响应token信息
//            return new Result(SuccessConstant.SUCCESS , MessageConstant.LOGIN_SUCCESS , map);
//        }
//        return new Result(SuccessConstant.FAIL , MessageConstant.LOGIN_FAIL);
//
//
//        //1.通过姓名和密码查询用户信息
////        User user = userService.login(vo);
////        if(ObjectUtil.isNotNull(user)){
////            Map<String, Object> map = new HashMap<>();
////            //2.当姓名和密码匹配时
////            // 创建访问Token令牌
////            String accessToken = JwtHelper.createToken(user.getId().longValue(), user.getUsername());
////            // 创建刷新Token令牌
////            String refreshToken = JwtHelper.refreshToken(accessToken);
////            map.put("accessToken", accessToken);
////            map.put("refreshToken", refreshToken);
////            //3.响应token信息
////            return new Result(SuccessConstant.SUCCESS , MessageConstant.LOGIN_SUCCESS , map);
////        }
////        return new Result(SuccessConstant.FAIL , MessageConstant.LOGIN_FAIL);
//    }
//
//    @ApiOperation("刷新令牌")
//    @PostMapping("refreshToken")
//    public Result refreshToken(@ApiParam("后端登录数据") String refreshToken){
//        if(!StringUtils.hasLength(refreshToken) || JwtHelper.isExpiration(refreshToken)){
//            throw new RefreshTokenInvalidException(MessageConstant.REFRESH_TOKEN_VERIFY_FAIL);
//        }
//
//        //获取令牌中登陆者信息
//        Long userId = JwtHelper.getUserId(refreshToken);
//        String userName = JwtHelper.getUserName(refreshToken);
//        //重新生成token令牌
//        String accessToken = JwtHelper.createToken(userId, userName);
//        refreshToken = JwtHelper.refreshToken(accessToken);
//        Map<String, Object> map = new HashMap<>();
//        map.put("accessToken", accessToken);
//        map.put("refreshToken", refreshToken);
//        return new Result(SuccessConstant.SUCCESS , MessageConstant.TOKEN_REFRESH , map);
//    }
//
//
//    @ApiOperation("登出")
//    @GetMapping("logout")
//    public Result logout(){
////        //SpringSecurity 补全登出
////        return new Result(SuccessConstant.SUCCESS , MessageConstant.LOGOUT_SUCCESS);
//        //获取认证信息 (管理员信息、账号状态、权限等)
//        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
//        LoginUser loginUser = (LoginUser)authentication.getPrincipal();
//        if(!ObjectUtils.isEmpty(loginUser)){
//            //在Redis中删除认证信息
//            Integer userId = loginUser.getUser().getId();
//            Boolean flag = redisTemplate.delete(RedisTokenConstant.USER_TOKEN + "::" + userId);
//            if(flag){
//                return new Result(SuccessConstant.SUCCESS , MessageConstant.LOGOUT_SUCCESS);
//            }
//        }
//        return new Result(SuccessConstant.FAIL , MessageConstant.LOGOUT_FAIL);
//    }
//
//}
package com.geek.factory.controller;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.geek.factory.constant.MessageConstant;
import com.geek.factory.constant.RedisTokenConstant;
import com.geek.factory.dto.LoginDTO;
import com.geek.factory.entity.User;
import com.geek.factory.exception.FactoryException;
import com.geek.factory.exception.RefreshTokenInvalidException;
import com.geek.factory.result.Result;
import com.geek.factory.constant.SuccessConstant;
import com.geek.factory.security.LoginUser;
import com.geek.factory.security.PhoneCodeAuthenticationToken;
import com.geek.factory.service.SmsService;
import com.geek.factory.service.UserService;
import com.geek.factory.utils.JwtHelper;
import com.geek.factory.vo.UserQueryVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;

/**
 * @author chenmin
 * @desc TODO
 * @date 2025/6/10
 */
//@RestController
//@RequestMapping("/admin")
//@Slf4j
@RestController
//@RequestMapping("/admin/auth")
@Api(tags = "后台系统-登录认证接口")
public class AuthController {
    @Autowired
    private UserService userService;
    @Autowired
    private SmsService smsService;
    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @ApiOperation("手机号验证码登录")
    @PostMapping("loginByPhone")
    public Result loginByPhone(@ApiParam("手机号验证码登录数据") @RequestBody LoginDTO dto) {
        // 1. 校验参数
        if (!StringUtils.hasLength(dto.getPhone()) || !StringUtils.hasLength(dto.getCode())) {
            return new Result(SuccessConstant.FAIL, MessageConstant.TELEPHONE_VALIDATECODE_NOTNULL);
        }

        try {
            // 2. 使用Spring Security进行认证
            PhoneCodeAuthenticationToken authenticationToken = new PhoneCodeAuthenticationToken(dto.getPhone(), dto.getCode());
            Authentication authenticate = authenticationManager.authenticate(authenticationToken);

            if (authenticate == null || !authenticate.isAuthenticated()) {
                return new Result(SuccessConstant.FAIL, MessageConstant.LOGIN_FAIL);
            }

            // 3. 认证成功，获取用户信息
            LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
            User user = loginUser.getUser();

            // 4. 生成token
            String accessToken = JwtHelper.createToken(user.getId().longValue(), user.getUsername());
            String refreshToken = JwtHelper.refreshToken(accessToken);
            Map<String, Object> map = new HashMap<>();
            map.put("accessToken", accessToken);
            map.put("refreshToken", refreshToken);

            // 5. 在Redis中存储一份认证通过的用户信息
            redisTemplate.opsForValue().set(RedisTokenConstant.USER_TOKEN+"::"+user.getId() , JSONUtil.toJsonStr(user));

            // 6. 返回
            return new Result(SuccessConstant.SUCCESS, MessageConstant.LOGIN_SUCCESS, map);
        } catch (Exception e) {
            return new Result(SuccessConstant.FAIL, "登录失败：" + e.getMessage());
        }
    }

    @ApiOperation("登录")
    @PostMapping("login")
    public Result login(@ApiParam("后端登录数据") @RequestBody UserQueryVO vo){
        //添加SpringSecurity之后  认证

        if(StrUtil.isEmpty(vo.getUsername()) || StrUtil.isEmpty(vo.getPassword())){
            throw new FactoryException(MessageConstant.LOGIN_FAIL);
        }
        //1.获取认证管理器中的认证信息
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(vo.getUsername() , vo.getPassword());
        //调用自定义的UserDetailsService中loadUserByUsername
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        //认证不通过
        if(ObjectUtils.isEmpty(authenticate)){
            throw new FactoryException(MessageConstant.LOGIN_FAIL);
        }

        //认证通过
        LoginUser loginUser = (LoginUser)authenticate.getPrincipal();
        if(loginUser!=null){
            User user = loginUser.getUser();
            Map<String, Object> map = new HashMap<>();
            //创建token数据并响应
            // 创建访问Token令牌
            String accessToken = JwtHelper.createToken(user.getId().longValue(), user.getUsername());
            // 创建刷新Token令牌
            String refreshToken = JwtHelper.refreshToken(accessToken);
            map.put("accessToken", accessToken);
            map.put("refreshToken", refreshToken);

            //在Redis中存储一份认证通过的用户信息
            redisTemplate.opsForValue().set(RedisTokenConstant.USER_TOKEN+"::"+user.getId() , JSONUtil.toJsonStr(user));
            //响应token信息
            return new Result(SuccessConstant.SUCCESS , MessageConstant.LOGIN_SUCCESS , map);
        }
        return new Result(SuccessConstant.FAIL , MessageConstant.LOGIN_FAIL);


        //1.通过姓名和密码查询用户信息
//        User user = userService.login(vo);
//        if(ObjectUtil.isNotNull(user)){
//            Map<String, Object> map = new HashMap<>();
//            //2.当姓名和密码匹配时
//            // 创建访问Token令牌
//            String accessToken = JwtHelper.createToken(user.getId().longValue(), user.getUsername());
//            // 创建刷新Token令牌
//            String refreshToken = JwtHelper.refreshToken(accessToken);
//            map.put("accessToken", accessToken);
//            map.put("refreshToken", refreshToken);
//            //3.响应token信息
//            return new Result(SuccessConstant.SUCCESS , MessageConstant.LOGIN_SUCCESS , map);
//        }
//        return new Result(SuccessConstant.FAIL , MessageConstant.LOGIN_FAIL);
    }

    @ApiOperation("刷新令牌")
    @PostMapping("refreshToken")
    public Result refreshToken(@ApiParam("后端登录数据") String refreshToken){
        if(!StringUtils.hasLength(refreshToken) || JwtHelper.isExpiration(refreshToken)){
            throw new RefreshTokenInvalidException(MessageConstant.REFRESH_TOKEN_VERIFY_FAIL);
        }

        //获取令牌中登陆者信息
        Long userId = JwtHelper.getUserId(refreshToken);
        String userName = JwtHelper.getUserName(refreshToken);
        //重新生成token令牌
        String accessToken = JwtHelper.createToken(userId, userName);
        refreshToken = JwtHelper.refreshToken(accessToken);
        Map<String, Object> map = new HashMap<>();
        map.put("accessToken", accessToken);
        map.put("refreshToken", refreshToken);
        return new Result(SuccessConstant.SUCCESS , MessageConstant.TOKEN_REFRESH , map);
    }


    @ApiOperation("登出")
    @GetMapping("logout")
    public Result logout(){
//        //SpringSecurity 补全登出
//        return new Result(SuccessConstant.SUCCESS , MessageConstant.LOGOUT_SUCCESS);
        //获取认证信息 (管理员信息、账号状态、权限等)
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser)authentication.getPrincipal();
        if(!ObjectUtils.isEmpty(loginUser)){
            //在Redis中删除认证信息
            Integer userId = loginUser.getUser().getId();
            Boolean flag = redisTemplate.delete(RedisTokenConstant.USER_TOKEN + "::" + userId);
            if(flag){
                return new Result(SuccessConstant.SUCCESS , MessageConstant.LOGOUT_SUCCESS);
            }
        }
        return new Result(SuccessConstant.FAIL , MessageConstant.LOGOUT_FAIL);
    }

}

